package org.xhy.sniffer.match;

import net.bytebuddy.description.annotation.AnnotationDescription;
import net.bytebuddy.description.annotation.AnnotationList;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static net.bytebuddy.matcher.ElementMatchers.isAnnotatedWith;
import static net.bytebuddy.matcher.ElementMatchers.named;

/**
 * @description: 注解匹配器
 * @gitee: https://gitee.com/XhyQAQ
 * @copyright: B站: https://space.bilibili.com/152686439
 * @Author: Xhy
 * @CreateTime: 2024-07-11 19:17
 */
public class AnnotationMatch implements ClassMatch{

    List<String> annotations;

    public AnnotationMatch(String... annotations){
        this.annotations = Arrays.asList(annotations);
    }

    @Override
    public ElementMatcher<? super TypeDescription> buildJunction() {
        ElementMatcher.Junction<? super TypeDescription> junction = null;
        for(String annotation : annotations){
            if (junction == null){
                junction = isAnnotatedWith(named(annotation));
            }else {
                junction.and(isAnnotatedWith(named(annotation)));
            }
        }
        return junction;
    }

    // 是否匹配，必须满足所有的注解
    @Override
    public boolean isMatch(TypeDescription typeDescription) {
        final ArrayList<String> arrayList = new ArrayList<>(annotations);
        // 获取注解 typeDescription 类上的所有注解
        final AnnotationList declaredAnnotations = typeDescription.getDeclaredAnnotations();
        for (AnnotationDescription declaredAnnotation : declaredAnnotations) {
            final String actualName = declaredAnnotation.getAnnotationType().getActualName();
            arrayList.remove(actualName);
        }
        return arrayList.isEmpty();
    }

    public static ClassMatch buildAnnotationMatch(String... annotations){
        return new AnnotationMatch(annotations);
    }
}
